# -*- coding: utf-8 -*-
import mechanize
from mechanize import Browser
import urllib
from copy import copy
import json
import re
import cStringIO as StringIO
import lxml.html
from lxml import etree
import cherrypy
from pymongo import Connection
import hashlib
import zlib
import sys
import datetime
import logging
from mongolog.handlers import MongoHandler
import urllib

# <!--- basic function
def getCRC32Unsign(textToHash=None):
    return str(zlib.crc32(textToHash) & 0xffffffffL)

def myBrowser(url, *cj):
    br = Browser()
    br.set_cookiejar(*cj)
    br.open(url)
    return br

def postRequest(br, idx=0, params=None):
    br.select_form(nr=idx)
    try:
        if params is not None:
            for p in params:
                br.form[p.keys()[0]] = p.values()[0]
            br.submit()
    except:
        pass
    return br

def dumpCookie(cookie):
    data = []
    for i in cookie:
        data.append(mechanize.lwp_cookie_str(i))
    for i in data:
        if re.search(r"PHPSESSID=", i):
            return reg_extract(r"PHPSESSID=(.+?);", i, 1)

def reg_extract(pat, mat, id):
    preg = re.compile(pat)
    m = preg.search(mat)
    if m != '':
        if (id>0):  return m.group(id)
        else:   return m.group()
    
def builTree(url, *cj):
    br = myBrowser(url, *cj)
    html = br.response().read()
    parser = etree.HTMLParser(encoding='utf-8')
    return etree.parse(StringIO.StringIO(html), parser)

def buildTree2(html):
    parser = etree.HTMLParser(encoding='utf-8')
    return etree.parse(StringIO.StringIO(html), parser)

def getElementText(elem):
    if elem is None: return ''
    if elem.text is None: return ''
    t = lxml.html.fromstring(etree.tostring(elem))
    return t.text_content().strip()

def getElementText2(elem):
    if elem is None: return ''
    return re.sub(r"\s+", ' ', stringify(elem)).strip()

def getAttributeText(node, attrb):
    if node is None or attrb == '': return ''
    return node.get(attrb)

def makeCookies(s_n, s_v, s_d, s_p):
    return mechanize.Cookie(version=0, name=s_n, value=s_v, port=None, port_specified=None, domain=s_d, 
                            domain_specified=True, domain_initial_dot=None, path=s_p, path_specified=None, 
                            secure=None, expires=None, discard=True, comment=None, comment_url=None, rest={}, 
                            rfc2109=False)

def getMD5Hash(textToHash=None):
    return hashlib.md5(textToHash).hexdigest()

def setcookie(s):
    sessID = makeCookies('PHPSESSID', s, '.banbe.net', '/')
    cj = mechanize.CookieJar()
    cj.set_cookie(sessID)
    return cj

# end basic function --->

class BanBe():
    profileURL = "http://banbe.net/{0}/profile"
    feedURL = "http://banbe.net/{0}/feed"
    friendsURL = "http://banbe.net/{0}/friend/index/searchfriends"
    postWallURL = "http://banbe.net/{0}/profile/index/publish/"
    notificationURL = "http://banbe.net/system/notifications/getnew"
        
    @cherrypy.expose
    def index(self):
        return "Nothing >> banbe.net"
    
    @cherrypy.expose
    def login(self, u, p):
        cj = mechanize.CookieJar()
        br = myBrowser('http://banbe.net', cj)
        br = postRequest(br, 0, [{'username': u}, {'password': p}])
        br.select_form(nr=0)
        br.submit()
        if re.search(r"http://banbe.net/.+/feed", br.response().geturl()):
            id = reg_extract('http://banbe.net/(.+)/feed', br.response().geturl(), 1)
            return json.dumps({'error': '0', 'status': 'Successful', 'id': id, 'sessionID': dumpCookie(cj)})
        return json.dumps({'error': '1', 'status': 'Email or password failed', 'id': '', 'sessionID': ''})
    
    @cherrypy.expose
    def postW(self, id='', s='', msg='', myself=1):
        if id == '' or msg == '':    return
        s = re.sub(r"[^a-z0-9]", '', s)
        if len(s) < 25:     return json.dumps({})
        if myself == 1:  data = urllib.urlencode({'message':msg, 'type': 'status', 'token': 'status', 'fromcall': '1'})
        else:   data = urllib.urlencode({'message':msg, 'type': 'status', 'token': 'status', 'fromcall': '0'})
        url = self.postWallURL.format(id)
        cj = setcookie(s)
        br = Browser()
        br.set_cookiejar(cj)
        br.addheaders = [("X-Requested-With", "XMLHttpRequest")]
        br.open(url, data)
        print br.response().info()
        
    @cherrypy.expose
    def notify(self, id='', s=''):
        s = re.sub(r"[^a-z0-9]", '', s)
        if len(s) < 25:     return json.dumps({})
        br = Browser()
        cj = setcookie(s)
        br.set_cookiejar(cj)
        br.addheaders = [("Accept", "application/json")]
        data = []
        try:
            if len(tree.xpath("//input[contains(@value, 'Đăng nhập')]".decode('utf-8'))) > 0:   return json.dumps({'error': 'mustLogin'})
            jdata = json.loads(br.open(self.notificationURL).read())
            html = re.sub(r"<!-- .+? -->", '', jdata['content'])
            html = "<html><body>{0}</body></html>".format(html)
            tree = buildTree2(html)
            for item in tree.xpath("//div[@class='notification-block']"):
                msg = re.sub(r"\s+", ' ', stringify(item.xpath(".//h4")[0]))
                time = re.sub(r"\s+", ' ', stringify(item.xpath(".//h3")[0]))
                avatar = item.xpath(".//img[contains(@src, 'avatar')]/@src")[0]
                data.append({'msg': msg, 'time': time, 'avatar': avatar})
        except:
            errMsg = "Error function notify({0}, {1}) >> {2}".format(id, s, sys.exc_info()[0])
            print errMsg
            log.error(errMsg)
            sys.exit()
        return json.dumps(data)
            
    @cherrypy.expose
    def wall(self, id='', s=''):
        s = re.sub(r"[^a-z0-9]", '', s)
        if len(s) < 25:     return json.dumps({})
        url = self.feedURL.format(id)
        cj = setcookie(s)
        br = myBrowser(url, cj)
        tree = buildTree2(br.response().read())
        data = []
        try:
            if len(tree.xpath("//input[contains(@value, 'Đăng nhập')]".decode('utf-8'))) > 0:   return json.dumps({'error': 'mustLogin'})
            for item in tree.xpath("//li[contains(@id, 'stream_item') and position()>1]"):
                titleNode = item.xpath(".//i")
                if len(titleNode) > 0:
                    title = getElementText(titleNode[0])
                avatar = item.xpath(".//div[@class='block01-main']/following-sibling::*[1]/img/@src")[0]
                # -- get comments --
                listComments = []
                commentNode = item.xpath(".//div[contains(@id, 'stream_comment_list')]")
                if len(commentNode) > 0:
                    commentNode = commentNode[0]
                    for iComment in commentNode.xpath(".//div[contains(@id, 'stream_comment_item')]"):
                        cm = {}
                        cm['title'] = getElementText2(iComment.xpath(".//h4")[0])
                        cm['time'] = getElementText2(commentNode.xpath(".//h3/b[contains(., 'lúc')]".decode('utf-8'))[0])
                        cm['userAvatar'] = getAttributeText(commentNode.xpath(".//div[@class='wrapper-highlight-main']/following-sibling::*[1]/img")[0], 'src')
                        listComments.append(cm)
                data.append({'title': title, 'avatar': avatar, 'comments': listComments})
                
        except:
            errMsg = "Error function wall({0}, {1}) >> {2}".format(id, s, sys.exc_info()[0])
            print errMsg
            log.error(errMsg)
            sys.exit()
        return json.dumps(data)
        
    @cherrypy.expose
    def profile(self, id='', s=''):
        url = self.profileURL.format(id)
        print url
        s = re.sub(r"[^a-z0-9]", '', s)
        if len(s) < 25:     return json.dumps({})
        sessID = makeCookies('PHPSESSID', s, '.banbe.net', '/')
        cj = mechanize.CookieJar()
        cj.set_cookie(sessID)
        info = []
        try:
            tree = builTree(url, cj)
            if len(tree.xpath("//h1[contains(., 'không tồn tại')]".decode('utf-8'))) > 0:   return json.dumps({})
            if len(tree.xpath("//input[contains(@value, 'Đăng nhập')]".decode('utf-8'))) > 0:   return json.dumps({'error': 'mustLogin'})
            bigImg = tree.xpath("//img[@id='bigimage']/@src")[0]
            thongtin = []
            for item in tree.xpath("//ul[@class='list01']/li"):
                thongtin.append("{0} {1}".format(item.xpath("./text()")[0], item.xpath("./span/text()")[0]))
            info.append({'avatar': bigImg, 'personalInfomation': thongtin})
        except:
            errMsg = "Error function profile({0}, {1}) >> {2}".format(id, s, sys.exc_info()[0])
            print errMsg
            log.error(errMsg)
            sys.exit()
            
        return json.dumps(info)
                    
    @cherrypy.expose
    def friends(self, id='', s=''):
        url = self.friendsURL.format(id)
        friendsList = []
        s = re.sub(r"[^a-z0-9]", '', s)
        if len(s) < 25:     return json.dumps({})
        sessID = makeCookies('PHPSESSID', s, '.banbe.net', '/')
        cj = mechanize.CookieJar()
        cj.set_cookie(sessID)
        try:
            while 1:
                tree = builTree(url, cj)
                # -- session invalid --
                if len(tree.xpath("//input[contains(@value, 'Đăng nhập')]".decode('utf-8'))) > 0:
                    return json.dumps({'error': 'mustLogin'})
                for item in tree.xpath("//ul[@class='mf_list_friend']/li"):
                    user = {}
                    user['avatar'] = getAttributeText(item.xpath(".//div[@class='mf_item_img']//img")[0], 'src')
                    user['name'] = getElementText(item.xpath(".//div[@class='mf_item_name']//a")[0])
                    user['linkProfile'] = mechanize.urljoin(url, getAttributeText(item.xpath(".//div[@class='mf_item_name']//a")[0], 'href'))
                    friendsList.append(user)
                nextPage = tree.xpath("//ul[@class='pagination']/li[@class='active']/following-sibling::*[1]/a")
                if len(nextPage) < 1:
                    break
                url = mechanize.urljoin(url, getAttributeText(nextPage[0], 'href'))
        except:
            errMsg = "Error function friends({0}, {1}) >> {2}".format(id, s, sys.exc_info()[0])
            print errMsg
            log.error(errMsg)
            sys.exit()
        return json.dumps(friendsList)
                
if __name__ == '__main__':
    
    stringify = etree.XPath("string()")
    log = logging.getLogger('BanBe')
    log.setLevel(logging.DEBUG)
    log.addHandler(MongoHandler.to('mongolog', 'log'))
    
    global_conf = {
        'global': {
        'server.socket_host': '127.0.0.1',
        'server.socket_port': 8888,
        'tools.encode.on': True,
        'tools.encode.encoding': 'UTF-8'
        },
    }
    cherrypy.config.update(global_conf)
    cherrypy.quickstart(BanBe())
    
    bb = BanBe()
#    bb.wall('1414053415', '6oukhj5nro09u30va4t17u02k6')
#    bb.wall('1378053039', '6oukhj5nro09u30va4t17u02k6')
    
    
    print ">> Finished at {0}".format(str(datetime.datetime.now()))
    sys.exit()
    